package net.huashitong.ssydt.provider.exam.service;

import huashitong.util.StringUtils;
import net.huashitong.ssydt.PaginationResult;
import net.huashitong.ssydt.exam.constant.ExamConsts;
import net.huashitong.ssydt.exam.entity.SsExamPaper;
import net.huashitong.ssydt.exam.entity.SsExamPaperProduce;
import net.huashitong.ssydt.exam.entity.SsExamPaperQuestion;
import net.huashitong.ssydt.exam.entity.SsExamQuestion;
import net.huashitong.ssydt.exam.entity.vo.SsExamPaperProduceQueryVO;
import net.huashitong.ssydt.exceptions.ServiceException;
import net.huashitong.ssydt.provider.exam.mapper.SsExamPaperProduceMapper;
import net.huashitong.ssydt.provider.sys.service.SsSysBasService;
import net.huashitong.ssydt.provider.utils.date.DateUtils;
import net.huashitong.ssydt.sys.constant.SysBasConsts;
import net.huashitong.ssydt.sys.entity.SsSysBas;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author <a href="mailto:yhy23456@163.com">huiyang.yu</a>
 * @since 2017.10.11
 */
@Service
@Transactional
public class SsExamPaperProduceServiceImpl implements SsExamPaperProduceService {

    private SsExamPaperProduceMapper mapper;

    private SsSysBasService ssSysBasService;

    private SsExamPaperService ssExamPaperService;

    private SsExamQuestionService ssExamQuestionService;

    private SsExamPaperQuestionService ssExamPaperQuestionService;

    private static final Random random = new Random();


    @Autowired
    public SsExamPaperProduceServiceImpl(SsExamPaperProduceMapper mapper,
                                         SsSysBasService ssSysBasService,
                                         SsExamPaperService ssExamPaperService,
                                         SsExamQuestionService ssExamQuestionService,
                                         SsExamPaperQuestionService ssExamPaperQuestionService) {
        this.mapper = mapper;
        this.ssSysBasService = ssSysBasService;
        this.ssExamPaperService = ssExamPaperService;
        this.ssExamQuestionService = ssExamQuestionService;
        this.ssExamPaperQuestionService = ssExamPaperQuestionService;
    }

    @Override
    public int deleteByPrimaryKey(Long id) {
        return mapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(SsExamPaperProduce record) {
        return mapper.insert(record);
    }

    @Override
    public int insertSelective(SsExamPaperProduce record) {
        return mapper.insertSelective(record);
    }

    @Override
    public SsExamPaperProduce selectByPrimaryKey(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(SsExamPaperProduce record) {
        return mapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(SsExamPaperProduce record) {
        return mapper.updateByPrimaryKey(record);
    }

    @Override
    public PaginationResult<SsExamPaperProduce> paginationQuery(SsExamPaperProduceQueryVO queryVO) {
        // 查询记录总数
        int total = mapper.paginationCount(queryVO);
        List<SsExamPaperProduce> list = new ArrayList<>();
        if (total > 0) {
            list = mapper.paginationQuery(queryVO);
        }
        PaginationResult<SsExamPaperProduce> result = new PaginationResult<>();
        result.setPageNumber(queryVO.getPageNumber());
        result.setPageSize(queryVO.getPageSize());
        result.setPageRecords(total);
        result.setList(list);
        return result;
    }

    @Override
    public void putProducePaper(Long id) {
        SsExamPaperProduce ssExamPaperProduce = selectByPrimaryKey(id);
        if (ssExamPaperProduce == null) {
            throw new ServiceException("生产记录不存在");
        }
        updateOrProducePaper(ssExamPaperProduce);
    }

    @Override
    @Scheduled(cron = "0 0 3 * * ?")
    public void scheduledProducePaper() {
        Calendar calendar = Calendar.getInstance();
        String today = new SimpleDateFormat("dd").format(calendar.getTime());
        if (today.compareTo("10") < 0) {
            calendar.set(Calendar.MONTH, -1);
        }
        String years = new SimpleDateFormat("yyyy").format(calendar.getTime());
        String months = new SimpleDateFormat("MM").format(calendar.getTime());
        List<SsExamPaperProduce> ssExamPaperProduces = this.findAllRandomOrder();
        for (SsExamPaperProduce ssExamPaperProduce : ssExamPaperProduces) {
            ssExamPaperProduce.setShowYearMonth(String.format("%s-%s", years, months));
            updateOrProducePaper(ssExamPaperProduce);
        }
    }

    @Override
    public List<SsExamPaperProduce> findAllRandomOrder() {
        return this.mapper.findAllRandomOrder();
    }

    /**
     * 更新或者生成试卷
     *
     * @param ssExamPaperProduce 试卷生产表对象
     */
    private void updateOrProducePaper(SsExamPaperProduce ssExamPaperProduce) {
        List<String> areas = getRandomStringList(ssExamPaperProduce.getArea());
        List<String> areaTypes = getStringList(ssExamPaperProduce.getExamRange());
        List<String> topics = getStringList(ssExamPaperProduce.getTopics());

        String[] stringArrays = ssExamPaperProduce.getShowYearMonth().split("-");
        String year = stringArrays[0].equals("0") ? DateUtils.getYear() : stringArrays[0];
        String month = stringArrays[1].equals("0") ? DateUtils.getMonth() : stringArrays[1];
        String belongYearMonth = String.format("%s-%s", year, month);

        String titlePrefix = String.format("%s年%s月", year, Integer.parseInt(month));
        SsSysBas sysBas = ssSysBasService.getByBasTypeAndDictValue(SysBasConsts.EXAM_TYPE, ssExamPaperProduce.getExamType());
        if (sysBas.getDictValue().equals("00")) {
            sysBas.setDictName("各类考试通用");
        }
        String titleSuffix = String.format("%s时事政治权威题库", sysBas.getDictName());
        for (String area : areas) {
            String paperName = getPaperTitle(titlePrefix, titleSuffix, ssExamPaperProduce.getExamType(), area);
            SsExamPaper ssExamPaper = ssExamPaperService.getByPaperName(paperName);
            if (ssExamPaper == null) {
                ssExamPaper = saveSsExamPaper(paperName, ssExamPaperProduce, area, belongYearMonth);
            }
            BigDecimal totalCoefficient = BigDecimal.valueOf(0);
            List<SsExamQuestion> ssExamQuestions = ssExamQuestionService
                    .queryByAreaWithAreaTypesWithTopics(area, areaTypes, topics, belongYearMonth);
            //跳过试卷已经存在题目
            totalCoefficient = filterSsExamQuestions(ssExamQuestions, totalCoefficient, ssExamPaper.getId());
            //生成试卷题目
            int numberQuestion = ssExamPaper.getQuestionNumber();
            List<SsExamPaperQuestion> ssExamPaperQuestionList = new ArrayList<>();
            for (SsExamQuestion ssExamQuestion : ssExamQuestions) {
                totalCoefficient = totalCoefficient.add(ssExamQuestion.getCoefficient());
                numberQuestion++;
                SsExamPaperQuestion ssExamPaperQuestion = getSsExamPaperQuestion(ssExamPaper, ssExamQuestion, numberQuestion);
                ssExamPaperQuestionList.add(ssExamPaperQuestion);
            }

            if (!ssExamPaperQuestionList.isEmpty()) {
                ssExamPaperQuestionService.batchInsert(ssExamPaperQuestionList);
            }

            //如果题目数为0 题库不生成，也就是删除试卷
            if (numberQuestion == 0) {
                ssExamPaperService.deleteByPrimaryKey(ssExamPaper.getId());
                continue;
            }

            //更新试卷题目数和难度系数
            BigDecimal coefficient = totalCoefficient.divide(BigDecimal.valueOf(numberQuestion), 2, BigDecimal.ROUND_DOWN);
            ssExamPaper.setCoefficient(coefficient);
            ssExamPaper.setQuestionNumber(numberQuestion);
            ssExamPaperService.updateQuestionNumberAndCoefficient(ssExamPaper);
        }
    }

    /**
     * 过滤已经存在的选择题
     *
     * @param ssExamQuestions
     * @param totalCoefficient
     * @param paperId
     * @return
     */
    private BigDecimal filterSsExamQuestions(List<SsExamQuestion> ssExamQuestions, BigDecimal totalCoefficient, Long paperId) {
        List<SsExamPaperQuestion> paperQuestions = ssExamPaperQuestionService.findByPaperId(paperId);
        if (paperQuestions != null && !paperQuestions.isEmpty()) {
            for (SsExamPaperQuestion paperQuestion : paperQuestions) {
                for (int i = 0; i < ssExamQuestions.size(); i++) {
                    SsExamQuestion question = ssExamQuestions.get(i);
                    if (question.getId().equals(paperQuestion.getQuestionId())) {
                        totalCoefficient = totalCoefficient.add(question.getCoefficient());
                        ssExamQuestions.remove(i);
                        break;
                    }
                }
            }
        }
        return totalCoefficient;
    }

    /**
     * 保存试卷
     *
     * @param paperName
     * @param ssExamPaperProduce
     * @param area
     * @param belongYearMonth
     * @return
     */
    private SsExamPaper saveSsExamPaper(String paperName, SsExamPaperProduce ssExamPaperProduce, String area, String belongYearMonth) {
        SsExamPaper ssExamPaper = new SsExamPaper();
        ssExamPaper.setPaperName(paperName);
        ssExamPaper.setPaperType(ssExamPaperProduce.getExamType());
        ssExamPaper.setArea(area);
        ssExamPaper.setBelongYearMonth(belongYearMonth);
        ssExamPaper.setTestNumber(0L);
        ssExamPaper.setCoefficient(BigDecimal.valueOf(0));
        ssExamPaper.setQuestionNumber(0);
        ssExamPaper.setPaperProduceId(ssExamPaperProduce.getId());
        ssExamPaperService.insert(ssExamPaper);
        return ssExamPaper;
    }

    /**
     * 保存试卷题目
     *
     * @param ssExamPaper
     * @param ssExamQuestion
     * @param numberQuestion
     */
    private SsExamPaperQuestion getSsExamPaperQuestion(SsExamPaper ssExamPaper, SsExamQuestion ssExamQuestion, int numberQuestion) {
        SsExamPaperQuestion ssExamPaperQuestion = new SsExamPaperQuestion();
        ssExamPaperQuestion.setSequence(numberQuestion);
        ssExamPaperQuestion.setPaperId(ssExamPaper.getId());
        ssExamPaperQuestion.setQuestionId(ssExamQuestion.getId());
        return ssExamPaperQuestion;
    }

    /**
     * 生成试卷标题
     *
     * @param titlePrefix
     * @param titleSuffix
     * @param examType
     * @return
     */
    private String getPaperTitle(String titlePrefix, String titleSuffix, String examType, String area) {
        String title;
        if (area.equals("00")) {
            switch (examType) {
                case ExamConsts.ExamType.CURRENCY:
                case ExamConsts.ExamType.KAOIYAN:
                    title = "全国";
                    break;
                case ExamConsts.ExamType.GUOKAO:
                    title = "国家";
                    break;
                case ExamConsts.ExamType.ZYLX:
                    title = "中央机关";
                    break;
                default:
                    title = "全国通用";
                    break;
            }
        } else {
            SsSysBas sysBas = ssSysBasService.getByBasTypeAndDictValue(SysBasConsts.PROVINCE, area);
            title = sysBas.getDictName();
        }

        return new StringBuilder(titlePrefix).append(title).append(titleSuffix).toString();
    }


    /**
     * 字符串转化为数组
     *
     * @param arrayStr
     * @return
     */
    private List<String> getStringList(String arrayStr) {
        List<String> list = new ArrayList<>();
        if (StringUtils.isNotBlank(arrayStr) && arrayStr.indexOf(",") > 0) {
            String[] arrays = arrayStr.split(",");
            list.addAll(Arrays.asList(arrays));
        } else if (StringUtils.isNotBlank(arrayStr)) {
            list.add(arrayStr);
        }
        return list;
    }


    /**
     * 字符串转化为乱序数组
     *
     * @param arrayStr
     * @return
     */
    private List<String> getRandomStringList(String arrayStr) {
        List<String> arraysList = getStringList(arrayStr);
        List<String> list = new ArrayList<>();
        int size;
        while ((size = arraysList.size()) > 0) {
            int i = random.nextInt(size);
            list.add(arraysList.get(i));
            arraysList.remove(i);
        }
        return list;
    }


}
